import java.net.Authenticator;
import java.net.MalformedURLException;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.ExitStatusException;
import org.apache.tools.ant.Task;

/**
 * @author Daniel Rijkhof <drijkhof@quintor.nl> First version
 * 
 * @author Arjan van der Veen <avdveen@palanthir.nl> Made changes to read the
 *         information from the RSS feed of Bamboo. If you make improvements,
 *         please also let know on http://veenbeest.nl/
 * 
 * @author Daniel Rijkhof <drijkhof@quintor.nl> Newer version of bamboo needs
 *         authentication to read rss feeds. Added a username and password
 *         parameters to the task
 *
 * @author Rinus Wiskerke Added support for basic (HTTP) authentication. Uses
 *         the same username and password fields but doesn't add them to the 
 *         URL. Usage: set property 'useBasicAuth' to 'true'
 */
public class GetBambooBuildDetails extends Task {

	private String server = null;
	private String buildplan = null;
	private String buildnumber = null;
	private String useBasicAuth = null;

	private String buildnumberProperty = null;
	private String buildstatusProperty = null;
	private String buildsuccessProperty = null;
	private String buildfailedProperty = null;

	private boolean failonerror = true;
	private String username;
	private String password;

	@Override
	public void execute() throws BuildException {
		checkAttributes();
		try {
			executeInternal();
		} catch (Exception e) {
			e.printStackTrace();
			throw new BuildException(e);
		}
	}

	private void checkAttributes() {
		if (buildplan == null) {
			throw new BuildException("buildplan attribute not set");
		}
		if (server == null) {
			throw new BuildException("server attribute not set");
		} else {
			if (!server.endsWith("/")) {
				server += "/";
			}
		}
	}

	private void executeInternal() throws Exception {
		BambooRssParser brp = new BambooRssParser();
		brp.setRssUrl(this.buildRssUr());
		List<BambooBuild> builds = brp.loadRssFeed();
		// find latest of asked build plan
		BambooBuild latest = null;
		for (BambooBuild bb : builds) {
			if (bb.getBuildplan().equals(this.buildplan)) {
				long bbDate = bb.getBuildDate().getTime();
				if (latest != null) {
					long latestDate = latest.getBuildDate().getTime();
					if (bbDate > latestDate) {
						latest = bb;
					}
				} else {
					latest = bb;
				}
			}
		}
		if (latest == null) {
			throw new BuildException("No build file for build plan '"
					+ buildplan + "' found");
		}
		this.interpretTaskProperties(latest);
	}

	private void interpretTaskProperties(BambooBuild bb) {
		boolean successful = !"failed".equalsIgnoreCase(bb.getBuildstatus());
		if (buildnumberProperty != null) {
			getProject().setUserProperty(buildnumberProperty,
					"" + bb.getBuildnumber());
		}
		if (buildstatusProperty != null) {
			getProject().setUserProperty(buildstatusProperty,
					bb.getBuildstatus());
		}
		if (buildfailedProperty != null) {
			getProject().setUserProperty(buildfailedProperty, "" + !successful);
		}
		if (buildsuccessProperty != null) {
			getProject().setUserProperty(buildsuccessProperty, "" + successful);
		}
		if (failonerror && !successful) {
			throw new ExitStatusException("bamboo build " + buildnumber
					+ " has failed", 1);
		}
	}

	private String buildRssUr() throws MalformedURLException {
		String rssUrl = this.server
				+ "rss/createAllBuildsRssFeed.action?feedType=rssAll";
		if (this.buildplan != null) {
			rssUrl += "&buildKey=" + buildplan;
		}
		if(this.useBasicAuth != null && Boolean.parseBoolean(this.useBasicAuth)){
			Authenticator.setDefault(new BasicAuthenticatorImpl(this.username, this.password));
			rssUrl += "&os_authType=basic";
		} else { 
			if (this.username != null) {
				rssUrl += "&os_username=" + username;
			}
			if (this.password != null) {
				rssUrl += "&os_password=" + password;
			}
		}
		return rssUrl;
	}

	public void setBuildplan(String buildplan) {
		this.buildplan = buildplan;
	}

	public void setBuildnumber(String buildnumber) {
		this.buildnumber = buildnumber;
	}

	public void setUseBasicAuth(String useBasicAuth) {
		this.useBasicAuth = useBasicAuth;
	}

	public void setBuildnumberProperty(String buildnumberProperty) {
		this.buildnumberProperty = buildnumberProperty;
	}

	public void setBuildstatusProperty(String buildstatusProperty) {
		this.buildstatusProperty = buildstatusProperty;
	}

	public void setBuildsuccessProperty(String buildsuccessProperty) {
		this.buildsuccessProperty = buildsuccessProperty;
	}

	public void setBuildfailedProperty(String buildfailedProperty) {
		this.buildfailedProperty = buildfailedProperty;
	}

	public void setFailonerror(boolean failonerror) {
		this.failonerror = failonerror;
	}

	public void setServer(String server) {
		this.server = server;
	}

	public void setUsername( String username ){
		this.username = username;
	}
	public void setPassword( String password ){
		this.password = password;
	}
	
}
